home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
dos6mm.zip
/
CMOSSAVE.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-03-31
|
21KB
|
462 lines
;****************************************************************************
; CMOSSAVE saves the contents of CMOS RAM to a file. Its syntax is:
;
; CMOSSAVE [d:][path]filename [/nnn]
;
; where "filename" is the name of the file to which CMOS data will be
; saved, and "nnn" specifies the number of bytes to save. Valid values
; for "nnn" are 64 to 256. If the /nnn switch is omitted, CMOSSAVE
; determines how many bytes of CMOS your PC contains and saves them all.
; Use CMOSRSTR to restore CMOS RAM data.
;****************************************************************************
CMOS_ADDR equ 70h ;CMOS address port
CMOS_DATA equ 71h ;CMOS data port
code segment
assume cs:code,ds:code
org 100h
begin: jmp main
copyright db "CMOSSAVE 2.0 Copyright (c) 1993 Jeff Prosise",13,10
db "From: PC Magazine DOS 6 Memory Management "
db "with Utilities",13,10,13,10,"$"
helpmsg db "Saves the configuration data stored in CMOS RAM to "
db "a file.",13,10,13,10
db "CMOSSAVE [d:][path]filename [/nnn]",13,10,13,10
db " filename Name of the file to which configuration "
db "data will be saved.",13,10
db " /nnn Number of bytes of CMOS RAM to save."
db 13,10,13,10
db "Use CMOSRSTR to restore CMOS configuration data."
crlf db 13,10,"$"
errmsg1 db "Syntax: CMOSSAVE [d:][path]filename [/nnn]",13,10,"$"
errmsg2 db "The file already exists. Replace it (Y/N)? $"
errmsg3 db "Invalid path or file name. File could not be "
db "created.",13,10,"$"
errmsg4 db "Error writing file to disk",13,10,"$"
errmsg5 db "Disk full",13,10,"$"
errmsg6 db "Invalid numeric parameter or value out of range"
db 13,10,"$"
msg db " bytes were copied from CMOS RAM to disk",13,10,"$"
handle dw ? ;File handle
filename dw 0 ;Address of file name
cmoslength dw ? ;Number of bytes to save
nnn dw 0 ;Value of "nnn" parameter
;****************************************************************************
; Procedure MAIN
;****************************************************************************
main proc near
cld ;Clear direction flag
mov si,81h ;Point SI to command line
call scanhelp ;Scan for "/?" switch
jnc main1 ;Branch if not found
mov ah,09h ;Display help text and exit
mov dx,offset helpmsg ;with ERRORLEVEL=0
int 21h
mov ax,4C00h
int 21h
;
; Parse the command line.
;
main1: call findchar ;Find a parameter
jc main2 ;Branch if end of line
cmp byte ptr [si],"/" ;Branch if the parameter
je main1a ;starts with a "/"
mov filename,si ;Save the address
call finddelim ;Find the end of the string
mov byte ptr [si],0 ;Convert file name to ASCIIZ
jc main2 ;Branch if end of line
inc si ;Advance SI
jmp main1 ;Loop back for more
main1a: inc si ;Skip the "/" character
call asc2bin ;Read and convert the number
mov dx,offset errmsg6 ;Error if carry returns set
jc error
cmp ax,64 ;Error if number is less
jb error ;than 64 or greater than
cmp ax,256 ;256
ja error
mov nnn,ax ;Save the value
jmp main1 ;Loop back for more
main2: cmp filename,0 ;Branch if a file name
jne main2a ;was entered
mov dx,offset errmsg1 ;Point DX to error message
error: mov ah,09h ;Display error message
int 21h
error_exit: mov ax,4C01h ;Exit with ERRORLEVEL=1
int 21h
main2a: mov cx,nnn ;Set CMOSLENGTH equal to
mov cmoslength,cx ;NNN and branch if a number
or cx,cx ;was entered on the command
jnz main3 ;line
call getlength ;Get CMOS length
mov cmoslength,cx ;Save the result
;
; Create the data file.
;
main3: mov ax,3D00h ;Attempt to open the file
mov dx,filename ;with DOS function 3Dh
int 21h
jc main4 ;Branch if the call failed
mov bx,ax ;Close the file
mov ah,3Eh
int 21h
mov ah,09h ;Ask if user wants to
mov dx,offset errmsg2 ;overwrite it
int 21h
ask: mov ah,08h ;Get the response
int 21h
or al,al
jnz compare
mov ah,08h
int 21h
jmp ask
compare: cmp al,"Y" ;Ask again if the answer
je yes ;isn't "Y" or "N"
cmp al,"y"
je yes
cmp al,"N"
je no
cmp al,"n"
jne ask
no: mov ah,02h ;Display "N" and abort
mov dl,"N"
int 21h
mov ah,09h
mov dx,offset crlf
int 21h
jmp error_exit
yes: mov ah,02h ;Display "Y" and continue
mov dl,"Y"
int 21h
mov ah,09h
mov dx,offset crlf
int 21h
main4: mov ah,3Ch ;Create the file by calling
xor cx,cx ;DOS function 3Ch
mov dx,filename
int 21h
mov dx,offset errmsg3 ;Error if the file could
jc main6a ;not be created
mov handle,ax ;Save the file handle
;
; Read the configuration data from CMOS RAM, compute the checksum, and
; write both to the file.
;
mov cx,8 ;Copy the CMOSSAVE signature
mov si,offset copyright ;to the output buffer
mov di,offset scanhelp
rep movsb
cld ;Clear direction flag
xor cx,cx ;Initialize counter
main5: mov al,cl ;Get address in AL
cli ;Interrupts off
out CMOS_ADDR,al ;Output CMOS address
jmp short $+2 ;I/O delay
jmp short $+2
in al,CMOS_DATA ;Read one byte of CMOS data
stosb ;Buffer the byte
sti ;Interrupts on
inc cx ;Increment counter
cmp cx,cmoslength ;Loop if there are more
jne main5 ;bytes to save
xor al,al ;Compute the checksum
mov cx,cmoslength
add cx,8
mov si,offset scanhelp
main6: add al,[si]
inc si
loop main6
stosb ;Copy checksum to buffer
mov ah,40h ;Write the data to the file
mov bx,handle
mov cx,cmoslength
add cx,9
mov dx,offset scanhelp
int 21h
mov dx,offset errmsg4
jc main6a ;Branch on error
cmp ax,cx ;Error if the disk is
je main7 ;full
mov dx,offset errmsg5
main6a: jmp error
;
; Close the file, display message, and exit.
;
main7: mov ah,3Eh ;Close the data file
mov bx,handle
int 21h
mov ah,09h ;Display copyright message
mov dx,offset copyright
int 21h
mov ax,cmoslength ;Display the number of
call bin2asc ;bytes that were saved
mov ah,09h
mov dx,offset msg
int 21h
mov ax,4C00h ;Exit with ERRORLEVEL=0
int 21h
main endp
;****************************************************************************
; GETLENGTH returns the number of bytes of CMOS RAM that this PC
; contains in CX. GETLENGTH will never return a value less than 64
; or greater than 256.
;****************************************************************************
getlength proc near
mov cx,64 ;Initialize counter
gl_loop: cli ;Interrupts off
mov al,cl ;Get address in AL
out CMOS_ADDR,al ;Output CMOS address
jmp short $+2 ;I/O delay
jmp short $+2
in al,CMOS_DATA ;Read one byte of CMOS data
mov bl,al ;Save the byte in BL
sti ;Interrupts on
mov al,0A5h ;Test this byte with
call testbyte ;alternating 1s and 0s
jc gl_exit
mov al,5Ah ;Test this byte with
call testbyte ;alternating 0s and 1s
jc gl_exit
mov al,00h ;Test this byte with
call testbyte ;all 0s
jc gl_exit
mov al,0FFh ;Test this byte with
call testbyte ;all 1s
jc gl_exit
cli ;Interrupts off
mov al,cl ;Get address in AL
out CMOS_ADDR,al ;Output CMOS address
jmp short $+2 ;I/O delay
jmp short $+2
mov al,bl ;Get original value in AL
out CMOS_DATA,al ;Restore the byte
sti ;Interrupts on
inc cx ;Increment counter
cmp cx,256 ;Loop back for more if
jne gl_loop ;CX is less than 256
mov al,80h ;Make sure NMI is enabled
out CMOS_ADDR,al ;if this happens to be a
jmp short $+2 ;PS/2
jmp short $+2
in al,CMOS_DATA
gl_exit: ret ;Return to caller
getlength endp
;****************************************************************************
; TESTBYTE tests a byte of CMOS RAM to see if it really does contain RAM.
; On entry, CL holds the CMOS address. On return, carry is clear if the
; byte contains RAM, set if it does not.
;****************************************************************************
testbyte proc near
mov ah,al ;Save test value in AH
cli ;Interrupts off
mov al,cl ;Get address in AL
out CMOS_ADDR,al ;Output CMOS address
jmp short $+2 ;I/O delay
jmp short $+2
mov al,ah ;Get test value in AL
out CMOS_DATA,al ;Output the test value
jmp short $+2 ;I/O delay
jmp short $+2
mov al,cl ;Get address in AL
out CMOS_ADDR,al ;Output CMOS address
jmp short $+2 ;I/O delay
jmp short $+2
in al,CMOS_DATA ;Read the test value back
sti ;Interrupts on
cmp al,ah ;Compare the values
je tb_exit ;Branch if they're equal
stc ;Set carry and return
ret
tb_exit: clc ;Clear carry and return
ret
testbyte endp
;****************************************************************************
; ASC2BIN converts the text pointed to by SI to a number and returns the
; value in AX. Carry returns set if the text contains an invalid character
; or if an overflow error occurred.
;****************************************************************************
asc2bin proc near
cld ;Clear direction flag
sub ax,ax ;Initialize registers
xor bh,bh
mov cx,10
a2b_loop: mov bl,[si] ;Get a character
inc si
cmp bl,20h ;Exit if space
je a2b_exit
cmp bl,09h ;Exit if tab
je a2b_exit
cmp bl,2Ch ;Exit if comma
je a2b_exit
cmp bl,0Dh ;Exit if carriage return
je a2b_exit
cmp bl,"0" ;Error if character is not
jb a2b_error ;a number
cmp bl,"9"
ja a2b_error
mul cx ;Multiply the value in AX
jc a2b_error ;by 10 and exit on overflow
sub bl,30h ;ASCII => binary
add ax,bx ;Add latest value to AX
jnc a2b_loop ;Loop back if no overflow
a2b_error: dec si ;Set carry and exit
stc
ret
a2b_exit: dec si ;Clear carry and exit
clc
ret
asc2bin endp
;****************************************************************************
; BIN2ASC converts a binary value in AX to ASCII form and displays it.
;****************************************************************************
bin2asc proc near
mov bx,10 ;Initialize divisor word and
xor cx,cx ;digit counter
b2a1: inc cx ;Increment digit count
xor dx,dx ;Divide by 10
div bx
push dx ;Save remainder on stack
or ax,ax ;Loop until quotient is zero
jnz b2a1
b2a2: pop dx ;Retrieve a digit from stack
add dl,30h ;Convert it to ASCII
mov ah,2 ;Display it
int 21h
loop b2a2 ;Loop until done
ret
bin2asc endp
;****************************************************************************
; SCANHELP scans the command line for a /? switch. If found, carry returns
; set and SI contains its offset. If not found, carry returns clear.
;****************************************************************************
scanhelp proc near
push si ;Save SI
scanloop: lodsb ;Get a character
cmp al,0Dh ;Exit if end of line
je scan_exit
cmp al,"?" ;Loop if not "?"
jne scanloop
cmp byte ptr [si-2],"/" ;Loop if not "/"
jne scanloop
add sp,2 ;Clear the stack
sub si,2 ;Adjust SI
stc ;Set carry and exit
ret
scan_exit: pop si ;Restore SI
clc ;Clear carry and exit
ret
scanhelp endp
;****************************************************************************
; FINDCHAR advances SI to the next non-white-space character. On return,
; carry set indicates EOL was encountered; carry clear indicates it was not.
;****************************************************************************
findchar proc near
lodsb ;Get the next character
cmp al,09h ;Loop if tab
je findchar
cmp al,20h ;Loop if space
je findchar
cmp al,2Ch ;Loop if comma
je findchar
dec si ;Point SI to the character
cmp al,0Dh ;Exit with carry set if end
je eol ;of line is reached
clc ;Clear carry and exit
ret
eol: stc ;Set carry and exit
ret
findchar endp
;****************************************************************************
; FINDDELIM advances SI to the next white-space character. On return,
; carry set indicates EOL was encountered.
;****************************************************************************
finddelim proc near
lodsb ;Get the next character
cmp al,09h ;Exit if tab
je fd_exit
cmp al,20h ;Exit if space
je fd_exit
cmp al,2Ch ;Exit if comma
je fd_exit
cmp al,0Dh ;Loop back for more if end
jne finddelim ;of line isn't reached
dec si ;Set carry and exit
stc
ret
fd_exit: dec si ;Clear carry and exit
clc
ret
finddelim endp
code ends
end begin